<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        // -----------------------------------------------------------------
        // 方法重写（Override） —— 继承中的多态
        class Animal {
            speak() {
                console.log("动物在叫");
            }
        }

        class Dog extends Animal {
            speak() {
                console.log("狗在喵喵叫");
            }
        }

        class Cat extends Animal {
            speak() {
                console.log("猫在汪汪叫");
            }
        }

        function makeItSpeak(animal) {
            animal.speak(); // 多态表现：同一个接口，调用不同的实现
        }

        /* 
            定义一个函数，这个函数接收一个Animal对象，然后调用这个对象的speak方法

            多态
                - 在 JS 中不会检查参数的类型，所以这就意味着任何数据都可以作为参数传递
                - 要调用某个函数，无需指定的类型，只要对象满足某些条件即可
                - 多态为我们提供了灵活性
        */

        makeItSpeak(new Dog()); // 狗在喵喵叫
        makeItSpeak(new Cat()); // 猫在汪汪叫

        // -----------------------------------------------------------------
        // 鸭子类型 -- JavaScript 的动态多态
        let dog = {
            speak: function () {
                console.log("汪汪");
            }
        };

        let robot = {
            speak: function () {
                console.log("机器人声音");
            }
        };

        function makeItSpeak(entity) {
            entity.speak(); // 不管是狗、机器人、猫，只要有 speak 方法就能用
        }

        makeItSpeak(dog);    // 汪汪
        makeItSpeak(robot);  // 机器人声音

        // -----------------------------------------------------------------
        // 函数多态（参数多样） —— 利用默认值、可变参数模拟
        function greet(name, age) {
            if (typeof age === "undefined") {
                console.log(`你好，${name}`);
            } else {
                console.log(`你好，${name}，你 ${age} 岁`);
            }
        }

        greet("小明");          // 你好，小明
        greet("小明", 18);       // 你好，小明，你 18 岁

    </script>
</head>

<body>

</body>

</html>